﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace treeView.SqlDb.Services
{
    public interface IRepository<TEntity> : IDisposable
         where TEntity : class
    {

        #region 数据缓存策略
        List<TEntity> IListTEntity();
        List<TEntity> IListTEntitysInclude(string modelName);
        #endregion

        #region Sql范畴
        /// <summary>
        /// 获取实体的IQueryable，状态Sql化
        /// </summary>
        /// <returns></returns>
        IQueryable<TEntity> GetAllSql();
        #endregion

        #region 单一ID传递
        /// <summary>
        /// 通过ID传递获取实体
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns></returns>
        TEntity GetById(object id);
        #endregion

        #region 基于Expression查找
        /// <summary>
        /// 基于提供的表达式，获取相应实体
        /// </summary>
        /// <typeparam name="Column"></typeparam>
        /// <param name="where">过滤条件</param>
        /// <param name="selectDto">筛选字段</param>
        /// <returns></returns>
        List<Column> SelectBy<Column>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, Column>> selectDto);

        /// <summary>
        /// 基于提供的表达式,获取相应实体总数,Sql一次性
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <returns></returns>
        int WhereCount(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// 基于提供的表达式,获取分页条件相应实体,Sql一次性
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <param name="PageIndex">起始页</param>
        /// <param name="PageSize">页数量</param>
        /// <returns></returns>
        List<TEntity> WhereBySelfTakeSkip(Expression<Func<TEntity, bool>> where, int? PageIndex, int? PageSize);



        void CancelTrack(TEntity currentEntry);

        /// <summary>
        /// （异步）基于提供的表达式,获取相应实体,Sql一次性
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <returns></returns>
        Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// (同步)集(集合)linq表达式，动态搜索参数，后截取数据(只可查询)
        /// </summary>
        /// <param name="where"></param>
        /// <returns>过滤查询条件减少数据缓存压力</returns>
        List<TEntity> ListWhereExpAsNoTracking(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// (同步)Linq表达式，动态搜索参数，后截取数据(只可查询)
        /// </summary>
        /// <param name="where"></param>
        /// <returns>过滤查询条件减少数据缓存压力</returns>
        TEntity SingleWhereExpAsNoTracking(Expression<Func<TEntity, bool>> where);
        /// <summary>
        /// (同步)Linq表达式，动态搜索参数，数据追踪(更新配套使用)
        /// </summary>
        /// <param name="where"></param>
        /// <returns>过滤查询条件减少数据缓存压力</returns>
        TEntity SingleWhereExp(Expression<Func<TEntity, bool>> where);

        /// <summary>
        /// 动态搜索单条参数，数据追踪无条件(更新配套使用)
        /// </summary>
        /// <returns></returns>
        TEntity FirstOne();

        /// <summary>
        /// 动态搜索集合参数，数据追踪无条件(更新配套使用)
        /// </summary>
        /// <param name="where">过滤条件</param>
        /// <returns></returns>
        List<TEntity> GetAllList(Expression<Func<TEntity, bool>> where);
        #endregion

        #region  (同步)增删改
        /// <summary>
        ///  创建新实体，并返回最后执行状态
        /// </summary>
        /// <param name="model">泛型</param>
        /// <returns></returns>
        bool Insert(TEntity model);
        /// <summary>
        /// 更新原实体，并返回最后执行状态
        /// </summary>
        /// <param name="model">泛型</param>
        /// <returns></returns>
        bool Update(TEntity model);

        /// <summary>
        /// 更新原实体，通过查找主键ID,设置回Unchanged状态
        /// </summary>
        /// <param name="model"></param>
        /// <param name="keyName"></param>
        /// <returns></returns>
        bool UpdateUnchanged(TEntity model, string keyName = null);

        /// <summary>
        /// 物理删除原实体，并返回最后执行状态
        /// </summary>
        /// <param name="model">泛型</param>
        /// <returns></returns>
        bool Delete(TEntity model);
        #endregion

        #region (同步)批量增删改查
        /// <summary>
        /// 批量创建实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <returns></returns>
        Tuple<bool, int> CreateRange(List<TEntity> list);
        /// <summary>
        /// 批量删除实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <returns></returns>
        Tuple<bool, int> DeleteRange(List<TEntity> list);
        /// <summary>
        ///  批量更新实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <returns></returns>
        Tuple<bool, int> UpdateRange(List<TEntity> list);
        /// <summary>
        /// 批量获取实体，并截取数据追踪，缓存更新时无反应 
        /// </summary>
        /// <returns></returns>
        List<TEntity> GetAsNoTrackingAllList();
        /// <summary>
        ///  批量获取实体，并截取数据追踪
        /// </summary>
        /// <returns></returns>
        List<TEntity> GetAllList();
        #endregion

        #region (异步)批量增删改查
        /// <summary>
        /// 批量获取实体，并截取数据追踪
        /// </summary>
        /// <returns></returns>
        Task<List<TEntity>> GetAllListAsync();
        /// <summary>
        /// 批量获取实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <param name="cancellationToken">任务令牌</param>
        /// <returns></returns>
        Task<Tuple<bool, int>> CreateRangeAsync(List<TEntity> list, CancellationToken cancellationToken = default);
        /// <summary>
        /// 批量获取实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <param name="cancellationToken">任务令牌</param>
        /// <returns></returns>
        Task<Tuple<bool, int>> DeleteRangeAsync(List<TEntity> list, CancellationToken cancellationToken = default);
        /// <summary>
        /// 批量获取实体，并返回最后执行状态与次数
        /// </summary>
        /// <param name="list">泛型</param>
        /// <param name="cancellationToken">任务令牌</param>
        /// <returns></returns>
        Task<Tuple<bool, int>> UpdateRangeAsync(List<TEntity> list, CancellationToken cancellationToken = default);
        #endregion

        #region 获取DbContext
        DbContext GetDbContext();
        #endregion
    }
}
